<!-- src/views/FileManager.vue -->
<template>
  <div class="file-manager-container">
    <h2>文件管理</h2>

    <!-- 操作按钮区域 -->
    <div class="action-buttons">
      <el-button type="primary" @click="openAddDialog" size="middle">
        <el-icon><Plus /></el-icon>
        新增文件
      </el-button>
    </div>

    <!-- 筛选区域 -->
    <div class="filter-section">
      <el-form inline class="filter-form" size="middle">
        <div class="filter-left">
          <el-form-item label="项目系统">
            <el-select v-model="filters.bizApp" placeholder="请选择项目" style="width: 140px;" clearable>
              <el-option v-for="item in projects" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
          </el-form-item>
          <el-form-item label="文件名称">
            <el-input 
              v-model="filters.fileName" 
              placeholder="请输入文件名" 
              style="width: 160px;" 
              clearable
            />
          </el-form-item>
          <el-form-item label="文件类型">
            <el-input 
              v-model="filters.fileSuffix" 
              placeholder="请输入文件后缀（如 .pdf）" 
              style="width: 120px;" 
              clearable
            />
          </el-form-item>
          <el-form-item label="文件备注">
            <el-input 
              v-model="filters.fileDesc" 
              placeholder="请输入备注关键词" 
              style="width: 120px;" 
              clearable
            />
          </el-form-item>
        </div>
        <div class="filter-right">
          <el-form-item>
            <el-button type="primary" @click="handleSearch">
              <el-icon><Search /></el-icon>
              搜索
            </el-button>
            <el-button @click="handleReset">
              <el-icon><Refresh /></el-icon>
              重置
            </el-button>
          </el-form-item>
        </div>
      </el-form>
    </div>

    <!-- 文件列表 -->
    <el-table 
      :data="fileList" 
      style="width: 100%; margin-top: 20px;"
      v-loading="loading"
      size="middle"
      stripe
    >
      <el-table-column prop="id" label="ID" width="80" />
      <el-table-column prop="fileName" label="文件名" show-overflow-tooltip />
      <el-table-column prop="bizApp" label="所属项目" width="120">
        <template #default="scope">
          <el-tag size="middle" type="info">
            {{ projects.find(p => p.value === scope.row.bizApp)?.label || scope.row.bizApp }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="fileDesc" label="备注" show-overflow-tooltip />
      <el-table-column prop="fileType" label="类型" width="177">
        <template #default="scope">
          <el-tag :type="getFileTypeColor(scope.row.fileType)" size="middle">
            {{ scope.row.fileType }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="createdAt" label="创建时间" width="180" />
      <el-table-column label="操作" width="300" fixed="right">
        <template #default="scope">
          <el-button size="small" @click="previewFile(scope.row)">
            <el-icon><View /></el-icon>
            预览
          </el-button>
          <el-button size="small" type="primary" @click="downloadFile(scope.row)">
            <el-icon><Download /></el-icon>
            下载
          </el-button>
          <el-button size="small" type="warning" @click="editFile(scope.row)">
            <el-icon><Edit /></el-icon>
            编辑
          </el-button>
          <el-button size="small" type="danger" @click="openDeleteDialog(scope.row)">
            <el-icon><Delete /></el-icon>
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页 -->
    <div class="pagination-container">
      <el-pagination
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :page-sizes="[10, 20, 50, 100]"
        :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>

    <!-- 新增/编辑弹窗 -->
    <el-dialog 
      v-model="dialogVisible" 
      :title="isEditing ? '编辑文件' : '新增文件'"
      width="600px"
      :close-on-click-modal="false"
    >
      <el-form 
        :model="form" 
        :rules="formRules" 
        ref="formRef"
        label-width="100px"
        label-position="right"
      >
        <el-form-item label="所属项目" prop="bizApp">
          <el-select v-model="form.bizApp" placeholder="请选择项目" style="width: 100%;">
            <el-option v-for="item in projects" :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
        </el-form-item>

        <el-form-item label="文件名称" prop="fileName">
          <el-input v-model="form.fileName" placeholder="请输入文件名" />
        </el-form-item>

        <el-form-item label="文件备注">
          <el-input v-model="form.fileDesc" placeholder="请输入备注信息" />
        </el-form-item>

        <el-form-item label="上传文件" prop="file" v-if="!isEditing">
          <el-upload
            class="upload-demo"
            :auto-upload="false"
            :before-upload="handleBeforeUpload"
            :on-change="handleFileChange"
            :on-remove="handleFileRemove"
            v-model:file-list="form.fileList"
            :limit="1"
            :disabled="uploadLoading"
            drag
          >
            <el-icon class="el-icon--upload"><UploadFilled /></el-icon>
            <div class="el-upload__text" v-if="!uploadLoading">
              将文件拖到此处，或<em>点击上传</em>
            </div>
            <div class="el-upload__text" v-else>
              正在上传文件...
            </div>
            <template #tip>
              <div class="el-upload__tip">
                支持 小于2GB的文件大小
              </div>
            </template>
          </el-upload>
          
          <!-- 上传进度显示 -->
          <div v-if="uploadLoading" class="upload-progress">
            <el-progress 
              :percentage="uploadProgress" 
              :status="uploadProgress === 100 ? 'success' : undefined"
            />
            <p class="upload-status">{{ uploadStatusText }}</p>
          </div>
        </el-form-item>

        <!-- 图片预览 -->
        <el-form-item v-if="isImage(form.fileType) && form.previewUrl">
          <div class="image-preview">
            <img :src="form.previewUrl" alt="预览图" />
          </div>
        </el-form-item>
      </el-form>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="cancelDialog" :disabled="uploadLoading">取消</el-button>
          <el-button 
            type="primary" 
            @click="submitForm" 
            :loading="submitLoading"
            :disabled="uploadLoading || (!isEditing && !form.uploadSuccess)"
          >
            {{ isEditing ? '更新' : '提交' }}
          </el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 预览弹窗 -->
    <el-dialog 
      v-model="previewVisible" 
      title="文件预览" 
      width="80%"
      :close-on-click-modal="false"
    >
      <div class="preview-container" v-if="currentPreviewFile">
        <div v-if="isImage(currentPreviewFile.fileType)" class="image-preview-large">
          <img :src="currentPreviewFile.previewUrl" :alt="currentPreviewFile.fileName" />
        </div>
        <div v-else-if="isPdf(currentPreviewFile.fileType)" class="pdf-preview">
          <iframe 
            :src="currentPreviewFile.fileUrl" 
            width="100%" 
            height="600px"
            style="border: none;"
          ></iframe>
        </div>
        <div v-else class="file-info">
          <el-icon size="48"><Document /></el-icon>
          <p>{{ currentPreviewFile.fileName }}</p>
          <p>此文件类型暂不支持预览</p>
          <el-button type="primary" @click="downloadFile(currentPreviewFile)" style="margin-top: 16px;">
            <el-icon><Download /></el-icon>
            下载文件
          </el-button>
        </div>
      </div>
    </el-dialog> 
    <!-- 删除确认框 -->
    <el-dialog
      v-model="deleteDialogVisible"
      title="删除确认"
      width="400px"
    >
      <div class="delete-confirm">
        <el-icon class="warning-icon"><WarningFilled /></el-icon>
        <p>确定要删除该配置吗？此操作不可恢复。</p>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="deleteDialogVisible = false">取消</el-button>
          <el-button type="danger" @click="confirmDelete" :loading="deleteLoading">确认删除</el-button>
        </div>
      </template>
    </el-dialog>


  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import * as qiniu from 'qiniu-js'
import { WarningFilled, QuestionFilled } from '@element-plus/icons-vue';
import request from '@/utils/request'
import {
  Plus, View, Download, Edit, Delete, UploadFilled, Document, Search, Refresh
} from '@element-plus/icons-vue'

// 文件名前缀生成函数
function generatePrefix() {
  const now = new Date()
  const pad = n => n.toString().padStart(2, '0')
  const randomChar = String.fromCharCode(65 + Math.floor(Math.random() * 26))
  return `${now.getFullYear().toString().slice(2)}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${pad(now.getHours())}-${randomChar}`
}

// 七牛上传（每次需新token）
function upload(file, onProgress, uptoken, customKey) {
  return new Promise((resolve, reject) => {
    let key = customKey || (new Date().getTime() + Math.random(1000) + file.name);
    let config = {
      useCdnDomain: true,
      region: qiniu.region.z2,
      domain: "https://static.jixingyun.cn",
      chunkSize: 100,
      forceDirect: true
    }
    let putExtra = { fname: file.name, params: {}, mimeType: [] }
    let observable = qiniu.upload(file, key, uptoken, putExtra, config)
    observable.subscribe({
      next: result => onProgress && result.total && onProgress(result.total.percent),
      error: reject,
      complete: resolve
    })
  })
}

// 获取系统应用配置
const getSysApplicationConfig = async () => {
  try {
    const response = await request.get('/public/getConfig', {
      params: {
        app: 'system',
        configKey: 'SysApplication'
      }
    });
    return response.data;
  } catch (error) {
    console.error('获取系统应用配置失败', error);
    ElMessage.error('获取系统应用配置失败');
    throw error;
  }
}

// 项目配置映射（包含域名信息）
const projectConfigMap = ref({})

// 根据项目代码获取域名
const getProjectDomain = (bizApp) => {
  const config = projectConfigMap.value[bizApp]
  return config?.fileDomain || 'https://image.wedsap.com' // 默认域名
}

// 处理文件URL，替换域名
const processFileUrl = (fileUrl, bizApp) => {
  if (!fileUrl) return fileUrl
  
  // 如果URL已经是完整URL，需要替换域名
  if (fileUrl.startsWith('http')) {
    // 提取文件key（去掉域名部分）
    const urlParts = fileUrl.split('/')
    const key = urlParts.slice(3).join('/') // 去掉 https://domain.com 部分
    const newDomain = getProjectDomain(bizApp)
    return `${newDomain}/${key}`
  }
  
  // 如果是相对路径，直接拼接域名
  const domain = getProjectDomain(bizApp)
  return `${domain}/${fileUrl}`
}

// 加载项目列表
const loadProjects = async () => {
  try {
    const configResponse = await getSysApplicationConfig();
    console.log('配置响应:', configResponse);
    
    if (configResponse && configResponse.success && configResponse.data && configResponse.data.configValue) {
      const configValue = configResponse.data.configValue;
      console.log('配置值:', configValue);
      
      const projectList = JSON.parse(configValue);
      console.log('解析后的项目列表:', projectList);
      
      // 构建项目配置映射
      projectConfigMap.value = {}
      projectList.forEach(item => {
        projectConfigMap.value[item.appCode] = {
          appName: item.appName,
          appCode: item.appCode,
          fileDomain: item.fileDomain || 'https://image.wedsap.com' // 默认域名
        }
      })
      
      // 构建下拉选项
      projects.value = projectList.map(item => ({
        label: item.appName,
        value: item.appCode
      }));
      
      console.log('项目配置映射:', projectConfigMap.value);
      console.log('最终的 projects.value:', projects.value);
    } else {
      throw new Error('配置数据格式不正确');
    }
  } catch (error) {
    console.error('加载项目列表失败', error);
    // 加载失败时使用默认项目列表和配置
    projects.value = [
      { label: '项目 A', value: 'projectA' },
      { label: '项目 B', value: 'projectB' },
      { label: '项目 C', value: 'projectC' }
    ];
    projectConfigMap.value = {
      'projectA': { appName: '项目 A', appCode: 'projectA', fileDomain: 'https://image.wedsap.com' },
      'projectB': { appName: '项目 B', appCode: 'projectB', fileDomain: 'https://image.wedsap.com' },
      'projectC': { appName: '项目 C', appCode: 'projectC', fileDomain: 'https://image.wedsap.com' }
    };
    ElMessage.warning('加载项目列表失败，使用默认配置');
  }
}

// 响应式数据
const loading = ref(false)
const submitLoading = ref(false)
const uploadLoading = ref(false)
const deleteLoading = ref(false)
const uploadProgress = ref(0)
const uploadStatusText = ref('')
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)

const filters = ref({
  bizApp: '',
  fileName: '',
  fileSuffix: '',
  fileDesc: ''
})

// 项目列表改为响应式数据，初始为空数组
const projects = ref([])

const fileList = ref([])

const dialogVisible = ref(false)
const previewVisible = ref(false)
const isEditing = ref(false)
const formRef = ref()

const form = ref({
  id: null,
  bizApp: '',
  fileName: '',
  fileDesc: '',
  fileType: '',
  file: null,
  fileList: [],
  previewUrl: '',
  uploadSuccess: false,
  fileUrl: '',
  fileKey: '',
  fileHash: ''
})

const currentPreviewFile = ref(null)

const formRules = {
  bizApp: [{ required: true, message: '请选择所属项目', trigger: 'change' }],
  fileName: [
    { required: true, message: '请输入文件名', trigger: 'blur' },
    { min: 1, max: 100, message: '文件名长度在 1 到 100 个字符', trigger: 'blur' }
  ],
  file: [{ required: true, message: '请选择要上传的文件', trigger: 'change' }]
}

const isImage = type => ['.png', '.jpg', '.jpeg', '.gif', '.bmp'].includes(type.toLowerCase())
const isPdf = type => type.toLowerCase() === '.pdf'

// 获取文件列表
const getFileList = async () => {
  try {
    loading.value = true
    const params = {
      page: currentPage.value - 1,
      pageSize: pageSize.value,
      ...filters.value
    }
    
    // 过滤空值参数
    Object.keys(params).forEach(key => {
      if (params[key] === '' || params[key] === null || params[key] === undefined) {
        delete params[key]
      }
    })
    
    const response = await request.get('/file/getFiles', { params })
    
    if (response.data.success) {
      fileList.value = response.data.data || []
      // 处理文件列表中的URL，确保使用正确的域名
      fileList.value = fileList.value.map(file => ({
        ...file,
        fileUrl: processFileUrl(file.fileUrl, file.bizApp)
      }))
      total.value = fileList.value.length
    } else {
      ElMessage.error(response.data.message || '获取文件列表失败')
    }
  } catch (error) {
    ElMessage.error('获取文件列表失败：' + (error.response?.data?.message || error.message))
  } finally {
    loading.value = false
  }
}

// 分页、筛选、重置等
const handleSizeChange = val => { 
  pageSize.value = val
  currentPage.value = 1
  getFileList()
}

const handleCurrentChange = val => { 
  currentPage.value = val
  getFileList()
}

const handleSearch = () => { 
  currentPage.value = 1
  getFileList()
}

const handleReset = () => {
  Object.assign(filters.value, { 
    bizApp: '', 
    fileName: '', 
    fileType: '', 
    fileDesc: '' 
  })
  currentPage.value = 1
  getFileList()
  ElMessage.info('筛选条件已重置')
}

const getFileTypeColor = type => {
  const typeMap = {
    '.pdf': 'danger', '.doc': 'primary', '.docx': 'primary', '.xls': 'success',
    '.xlsx': 'success', '.ppt': 'warning', '.pptx': 'warning', '.png': 'info',
    '.jpg': 'info', '.jpeg': 'info', '.gif': 'info', '.bmp': 'info',
    '.txt': '', '.zip': 'warning', '.mp4': 'success', '.psd': 'primary'
  }
  return typeMap[type.toLowerCase()] || 'info'
}

// 弹窗逻辑
const openAddDialog = () => { 
  isEditing.value = false; 
  dialogVisible.value = true; 
  resetForm() 
}

const resetForm = () => {
  if (form.value.previewUrl && form.value.previewUrl.startsWith('blob:')) {
    URL.revokeObjectURL(form.value.previewUrl)
  }
  Object.assign(form.value, {
    id: null, bizApp: '', fileName: '', fileDesc: '', fileType: '', file: null,
    fileList: [], previewUrl: '', uploadSuccess: false, fileUrl: '', fileKey: '', fileHash: ''
  })
  uploadLoading.value = false
  uploadProgress.value = 0
  uploadStatusText.value = ''
  formRef.value && formRef.value.resetFields()
}

// 上传前校验
const handleBeforeUpload = (file) => {
  const isLt2G = file.size / 1024 / 1024 / 1024 < 2
  if (!isLt2G) {
    ElMessage.error('上传文件大小不能超过 2GB!')
    return false
  }
  const allowedTypes = [
    'image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/bmp',
    'application/pdf', 'application/msword',
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
    'text/plain', 'application/zip', 'application/x-zip-compressed', 'video/mp4'
  ]
  if (!allowedTypes.includes(file.type)) {
    ElMessage.error('不支持的文件类型!')
    return false
  }
  return false // 阻止自动上传
}

// 允许未提交时可多次替换文件（覆盖上传不会出 bug）
const handleFileChange = async (uploadFile) => {
  // 先清空上一次的文件和状态
  handleFileRemove()
  // 现在处理新文件
  form.value.fileList = [uploadFile]
  const prefix = generatePrefix()
  const originName = uploadFile.name
  const fullName = `${prefix}-${originName}`

  form.value.file = uploadFile.raw
  form.value.fileName = fullName
  form.value.fileType = '.' + originName.split('.').pop().toLowerCase()
  form.value.uploadSuccess = false

  if (isImage(form.value.fileType)) {
    form.value.previewUrl = URL.createObjectURL(uploadFile.raw)
  }

  uploadLoading.value = true
  uploadProgress.value = 0
  uploadStatusText.value = '正在上传...'

  try {
    // 获取 token
    const uptokenRes = await getQiniuToken(form.value.bizApp, fullName)
    const uptoken = uptokenRes.data

    // 上传
    const result = await upload(uploadFile.raw, percent => {
      uploadProgress.value = percent
      uploadStatusText.value = `上传进度: ${Math.round(percent)}%`
    }, uptoken, fullName)

    // 使用项目配置的域名
    const domain = getProjectDomain(form.value.bizApp)
    form.value.fileUrl = `${domain}/${result.key}`
    form.value.uploadSuccess = true
    form.value.fileKey = result.key
    form.value.fileHash = result.hash

    uploadProgress.value = 100
    uploadStatusText.value = '文件上传成功!'
    ElMessage.success('文件上传成功！')

    formRef.value?.validateField('file')
  } catch (error) {
    ElMessage.error(error.message || '文件上传失败')
    handleFileRemove()
  } finally {
    uploadLoading.value = false
  }
}

const handleFileRemove = () => {
  if (form.value.previewUrl && form.value.previewUrl.startsWith('blob:')) {
    URL.revokeObjectURL(form.value.previewUrl)
  }
  Object.assign(form.value, {
    file: null, fileName: '', fileType: '', previewUrl: '', uploadSuccess: false, fileUrl: '', fileKey: '', fileHash: ''
  })
  form.value.fileList = []
  uploadProgress.value = 0
  uploadStatusText.value = ''
  uploadLoading.value = false
}

// 新增保存文件接口
const saveFile = async () => {
  const params = {
    fileName: form.value.fileName,
    fileType: form.value.fileType,
    fileUrl: form.value.fileUrl,
    bizApp: form.value.bizApp,
    fileSuffix: form.value.fileType,
    fileHash: form.value.fileHash,
    fileDesc: form.value.fileDesc
  }
  await request.post('/file/save', params)
}

const submitForm = async () => {
  if (!formRef.value) return
  try {
    await formRef.value.validate()
    if (!isEditing.value && !form.value.uploadSuccess) {
      ElMessage.error('请先上传文件')
      return
    }
    submitLoading.value = true

    // 保存到后端
    await saveFile()
    ElMessage.success(isEditing.value ? '文件更新成功' : '文件添加成功')
    
    dialogVisible.value = false
    // 刷新列表
    await getFileList()
  } catch (error) {
    ElMessage.error('提交失败：' + (error.response?.data?.message || error.message))
  } finally {
    submitLoading.value = false
  }
}

const previewFile = (row) => {
  currentPreviewFile.value = { 
    ...row,
    // 确保预览时使用正确的域名
    fileUrl: processFileUrl(row.fileUrl, row.bizApp)
  }
  
  if (isImage(row.fileType)) {
    currentPreviewFile.value.previewUrl = currentPreviewFile.value.fileUrl || 'https://via.placeholder.com/800x600?text=' + encodeURIComponent(row.fileName)
  }
  previewVisible.value = true
}

const downloadFile = (row) => {
  // 使用处理后的URL进行下载
  const downloadUrl = processFileUrl(row.fileUrl, row.bizApp)
  
  if (downloadUrl) {
    try {
      const link = document.createElement('a')
      link.href = downloadUrl
      link.download = row.fileName
      link.target = '_blank'
      link.rel = 'noopener noreferrer'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      ElMessage.success(`开始下载：${row.fileName}`)
    } catch (error) {
      window.open(downloadUrl, '_blank')
    }
  } else {
    ElMessage.warning('文件下载链接不存在')
  }
}

// 删除弹窗相关逻辑
const deleteDialogVisible = ref(false)
const currentDeleteFile = ref(null)

const openDeleteDialog = (file) => {
  currentDeleteFile.value = file
  deleteDialogVisible.value = true
}

const confirmDelete = async () => {
  if (!currentDeleteFile.value) return
  
  try {
    deleteLoading.value = true
    const response = await request.delete(`/file/delete`, {
      params: { id: currentDeleteFile.value.id }
    })
    
    if (response.data.success) {
      ElMessage.success('文件删除成功')
      deleteDialogVisible.value = false
      currentDeleteFile.value = null
      // 刷新列表
      await getFileList()
    } else {
      ElMessage.error(response.data.message || '删除文件失败')
    }
  } catch (error) {
    ElMessage.error('删除文件失败：' + (error.response?.data?.message || error.message))
  } finally {
    deleteLoading.value = false
  }
}

const editFile = (row) => {
  isEditing.value = true
  dialogVisible.value = true
  Object.assign(form.value, { 
    ...row, 
    fileList: [], 
    uploadSuccess: true,
    // 确保编辑时使用正确的域名
    fileUrl: processFileUrl(row.fileUrl, row.bizApp)
  })
}

const cancelDialog = () => {
  if (uploadLoading.value) {
    ElMessage.warning('文件正在上传中，请稍后再试')
    return
  }
  dialogVisible.value = false
  resetForm()
}

// 获取七牛token（需带参数）
async function getQiniuToken(bizApp, originFileName) {
  const res = await request.get('/file/createToken', {
    params: { originFileName }
  })
  return { data: res.data.data || res.data }
}

// 组件挂载时获取项目列表和文件列表
onMounted(async () => {
  await loadProjects()
  await getFileList()
})
</script>

<!-- 样式部分保持不变 -->
<style scoped>
/* 样式同你的原始风格，略去如有需求可补充 */
.file-manager-container {
  background-color: #fff;
  padding: 24px;
  border-radius: 8px;
  min-height: calc(100vh - 120px);
}
.filter-section {
  margin-bottom: 6px;
  padding: 6px;
  border-radius: 6px;
}
.filter-form {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}
.filter-left {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  flex: 1;
}
.filter-right {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
.filter-form .el-form-item {
  margin-bottom: 0 !important;
  flex-shrink: 0;
}
.action-buttons {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 6px;
  padding: 6px;
  border-radius: 6px;
}
.pagination-container {
  display: flex;
  justify-content: center;
  margin-top: 20px;
  padding: 20px 0;
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}
.image-preview {
  text-align: center;
  padding: 16px;
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  background-color: #fafafa;
}
.image-preview img {
  max-width: 100%;
  max-height: 200px;
  object-fit: contain;
  border-radius: 4px;
}
.image-preview-large {
  text-align: center;
  max-height: 70vh;
  overflow: auto;
}
.image-preview-large img {
  max-width: 100%;
  height: auto;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.file-info {
  text-align: center;
  padding: 40px;
  color: #666;
}
.file-info p {
  margin: 12px 0;
  font-size: 16px;
}
.preview-container {
  min-height: 200px;
}
.upload-progress {
  margin-top: 16px;
  padding: 16px;
  background-color: #f8f9fa;
  border-radius: 6px;
  border: 1px solid #e9ecef;
}
.upload-status {
  margin-top: 8px;
  font-size: 14px;
  color: #666;
  text-align: center;
}
.filter-right .el-form-item:last-child {
  margin-right: 0 !important;
}
:deep(.el-upload-dragger) {
  border: 2px dashed #d9d9d9;
  border-radius: 6px;
  width: 370px;
  height: 187px;
  text-align: center;
  background-color: #fafafa;
  transition: all 0.3s;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding-top: 20px;
}
:deep(.el-upload-dragger:hover) {
  border-color: #409eff;
  background-color: #f0f9ff;
}
:deep(.el-upload-dragger.is-dragover) {
  border-color: #409eff;
  background-color: #f0f9ff;
}
:deep(.el-icon--upload) {
  font-size: 48px;
  color: #c0c4cc;
  margin-bottom: 16px;
}
:deep(.el-upload__text) {
  color: #606266;
  font-size: 16px;
  margin-bottom: 12px;
}
:deep(.el-upload__tip) {
  color: #909399;
  font-size: 12px;
  position: absolute;
  bottom: 17px;
  left: 0;
  right: 0;
  text-align: center;
}
:deep(.upload-demo) {
  position: relative;
  margin-bottom: 35px;
}
:deep(.el-upload--disabled .el-upload-dragger) {
  background-color: #f5f7fa;
  border-color: #e4e7ed;
  cursor: not-allowed;
}
:deep(.el-upload--disabled .el-upload__text) {
  color: #c0c4cc;
}
@media (max-width: 1200px) {
  .filter-form {
    flex-direction: column;
    align-items: stretch;
  }
  .filter-left {
    justify-content: flex-start;
  }
  .filter-right {
    justify-content: flex-end;
    margin-top: 12px;
  }
}
@media (max-width: 768px) {
  .filter-left {
    flex-direction: column;
    align-items: stretch;
  }
  .filter-right {
    justify-content: center;
  }
  :deep(.el-upload-dragger) {
    width: 100%;
    max-width: 270px;
  }
}
.warning-icon {
  font-size: 24px;
  color: #e6a23c;
}
.delete-confirm {
  display: flex;
  align-items: center;
  gap: 16px;
}
</style>